using Gtk;
using Gee;
using WebKit;
using Meridian.Side;
using Meridian.Content;
using Gdk;

namespace Meridian {

public class Meridian : Gtk.Window {

    private const string TITLE = "Meridian";
    private const string ICON = "meridian.svg";
    private const string DEFAULT_HOME_URL = "http://www.google.com/";
    private const string DEFAULT_SEARCH_URL = "http://www.google.com/search?q=%s";
    private const string SEARCH_TOKEN = "%s";
    private const string DEFAULT_PROTOCOL = "http";
    private const string CONTENT = "content";

    private Regex protocol_regex;

    private Entry search_bar;
    private ToolButton back_button;
    private ToolButton forward_button;
    private ToolButton reload_button;
    private ToolButton stop_button;
    private ToolButton home_button;
    private ToolButton new_tab_button;
    private ToolButton bookmark_button;
    
    private WebBook web_book;
    private Widget side_bar;
    
    private SideStore side_store; 
    
    public Meridian () {
        set_default_size (1200, 600);
        
        print ("Launching Meridian\n");

        try {
            this.protocol_regex = new Regex (".*://.*");
        } catch (RegexError e) {
            critical ("%s", e.message);
        }
        
        try {
        	this.icon = new Pixbuf.from_file (ICON);
    	} catch (GLib.Error error) {
        	print ("Could not find " + ICON + error.message);	
    	}

        create_widgets ();
        connect_buttons ();
        connect_webbook ();
        this.search_bar.grab_focus ();
    }
    
    public static int main (string[] args) {
        Gtk.init (ref args);

        var browser = new Meridian ();
        browser.start ();

        Gtk.main ();

        return 0;
    }
    

    private void create_widgets () {
        this.side_store = new SideStore ();
        side_store.recover ();
		
		//construct toolbar
        Toolbar toolbar = new Toolbar ();
        //buttons
        this.back_button = new ToolButton.from_stock (Stock.GO_BACK);
        this.forward_button = new ToolButton.from_stock (Stock.GO_FORWARD);
        this.stop_button = new ToolButton.from_stock (Stock.STOP);
        this.reload_button = new ToolButton.from_stock (Stock.REFRESH);
        this.home_button = new ToolButton.from_stock (Stock.HOME);
        this.new_tab_button = new ToolButton.from_stock (Stock.ADD);       
        toolbar.add (this.back_button);
        toolbar.add (this.forward_button);
        toolbar.add (new SeparatorToolItem ());
        toolbar.add (this.stop_button);
        toolbar.add (this.reload_button);
        toolbar.add (new SeparatorToolItem ());
        toolbar.add (this.home_button);
        toolbar.add (this.new_tab_button);
        toolbar.add (new SeparatorToolItem ());
        //bookmark button
        this.bookmark_button = new ToolButton.from_stock (Stock.SAVE);
        toolbar.add (this.bookmark_button);
        //search bar
        this.search_bar = new Entry ();
        this.search_bar.set_icon_from_stock (EntryIconPosition.PRIMARY, Stock.FIND);
        this.search_bar.set_icon_from_stock (EntryIconPosition.SECONDARY, Stock.MEDIA_PLAY);
        var search_bar_container = new ToolItem ();
        search_bar_container.add (search_bar);
        search_bar_container.set_expand(true);
        toolbar.add(search_bar_container);
        
        
        //construct side bar          
        var side_bar = new TreeView ();
        side_bar.insert_column_with_attributes (-1, "Type", new CellRendererText (), "text", 0, null);
        side_bar.set_model (this.side_store);
        side_bar.expand_all ();

		//create tabs and add one
        this.web_book = new WebBook ();            
        this.add_tab ();
        
        //construct chrome
        VBox window = new VBox (false, 0);
        window.pack_start (toolbar, false);
        
        HPaned panes = new HPaned ();
        panes.add1 (side_bar);
        panes.add2 (web_book);
        window.pack_start (panes);        
        
        add (window);
    }

    private void connect_buttons () {
        this.destroy.connect (Gtk.main_quit);

        //button callbacks
        this.search_bar.activate.connect (search);
        this.search_bar.grab_focus.connect (select_search_bar);
               
        this.new_tab_button.clicked.connect (add_tab);
        this.bookmark_button.clicked.connect (add_bookmark);
    }

    private void connect_webbook () {
		//button callbacks
		this.home_button.clicked.connect (this.go_home);
        this.back_button.clicked.connect (this.web_book.go_back);
        this.forward_button.clicked.connect (this.web_book.go_forward);
        this.reload_button.clicked.connect (this.web_book.reload);
        this.stop_button.clicked.connect (this.web_book.stop_loading);
        
        //web view callbacks
        this.web_book.title_changed.connect ((source, title) => {
            this.title = "%s - %s".printf (title, Meridian.TITLE);
        });

        this.web_book.load_started.connect (update_buttons);
        this.web_book.load_progress_changed.connect (update_progress);
        this.web_book.load_finished.connect (page_loaded);
    }

    private void update_buttons () {
        this.back_button.sensitive = this.web_book.get_active_content ().can_go_back ();
        this.forward_button.sensitive = this.web_book.get_active_content ().can_go_forward ();
    }
    
    private void page_loaded () {
        update_progress (0);
        add_history ();
    }

    private void update_progress (int progress) {
        this.search_bar.set_progress_fraction (progress / 100.0);
    }

    private void search () {
        string query = this.search_bar.text;
        string url;
        if (this.protocol_regex.match (query)) {
            url = query;
        }
        else {
            url = get_search_url (query, this.DEFAULT_SEARCH_URL);
        }
        
        this.web_book.go_to (url);
    }

    private void select_search_bar () {
        int end = this.search_bar.get_text ().length;
        this.search_bar.set_position (end);
        this.search_bar.select_region (0, end);
    }

    private string get_search_url(string query, string DEFAULT_SEARCH_URL) {
        return DEFAULT_SEARCH_URL.replace(this.SEARCH_TOKEN, query);
    }

    public void start () {
        show_all ();
        go_home ();
    }

    private void go_home () {
        this.web_book.go_to (Meridian.DEFAULT_HOME_URL);
    }

    private void add_tab () {
        this.web_book.add_tab ("Home");
        this.go_home ();
    }
    
    private void add_bookmark () {     
        WebView web_view = this.web_book.get_active_content ();
        var title =  web_view.get_title ();
		var url =  web_view.get_uri ();
        print ("Adding bookmark [" + title + " : " + url + "]\n");
        var bookmark = new Bookmark (title, url);
        this.side_store.store_bookmark (bookmark);
        this.side_bar.show_all ();
    }
    
    private void add_history () {
        WebView web_view = this.web_book.get_active_content ();
        var title =  web_view.get_title ();
		var url =  web_view.get_uri ();
        print ("Adding history [" + title + " : " + url + "]\n");
        var history = new History (title, url);
        this.side_store.store_history (history);
        this.side_bar.show_all ();
    }

}
}
